<?php

interface Ebx_Registry_Interface {

	function set($key, $value);

	function get($key);

	function has($key);

	function clear($key);

	function setId($id);

	function getId();

	function toArray();

}

abstract class Ebx_Registry implements Ebx_Registry_Interface {

	protected $_id = null;

	protected $_data = array();

	protected $_storage = null;

	function __construct($id) {
		$this->setId($id);
	}

	function setId($id) {
		if ($id) {
			$this->_id = (string)$id;
		} else {
			trigger_error("Empty registry ID in ".__CLASS__, E_USER_ERROR);
		}
	}

	function getId() {
		return $this->_id;
	}

	function toArray() {
		return $this->_data;
	}

	function toJson($jsonOptions = 0) {
		return json_encode($this->toArray(), $jsonOptions);
	}

	function set($key, $value) {
		$this->_data[$key] = $value;
	}

	function get($key) {
		return $this->has($key) ? $this->_data[$key] : null;
	}
	
	function has($key) {
		return isset($this->_data[$key]);
	}

	function clear($key) {
		if (isset($this->_data[$key])) {
			unset($this->_data[$key]);
		}
	}

	function setStorage(Ebx_Storage $storage) {
		$this->_storage = $storage;
	}

	function getStorage() {
		return $this->_storage;
	}

}

class Ebx_Registry_Array extends Ebx_Registry implements Ebx_Registry_Interface, ArrayAccess, Countable {

	function offsetSet($key, $value) {
		$this->set($key, $value);
	}

	function offsetGet($key) {
		return $this->get($key);
	}

	function offsetExists($key) {
		return $this->has($key);
	}

	function offsetUnset($key) {
		$this->clear($key);
	}

	function count() {
		return count($this->_data);
	}

}

class Ebx_Registry_Session extends Ebx_Registry_Array implements Ebx_Registry_Interface, ArrayAccess {

	protected $_isSessionCreated = false;

	function set($key, $value) {
		$this->_startSession();
		$this->_data[$key] = $value;
	}

	function get($key) {
		$this->_startSession();
		return $this->has($key) ? $this->_data[$key] : null;
	}

	function has($key) {
		$this->_startSession();
		return isset($this->_data[$key]);
	}

	function clear($key) {
		$this->_startSession();
		if (isset($this->_data[$key])) {
			unset($this->_data[$key]);
		}
	}

	protected function _startSession() {
		if (!$this->_isSessionCreated) {
			$id = $this->getId();
			if (!is_array($_SESSION)) {
				session_start();
			}
			if (is_array($_SESSION)) {
				if (!isset($_SESSION[$id])) {
					$_SESSION[$id] = array();
				}
				$this->_data = & $_SESSION[$id];
				$this->_isSessionCreated = true;
			} else {
				trigger_error("Create session error in ".__CLASS__, E_USER_ERROR);
			}
		}
	}

}

class Ebx_Registry_Manager {

	protected static $_objects = array();

	protected static $_defaultType = 'array';

	static function getRegistry($id, $type = null) {
		$class = self::getFullClassName($type);
		if (isset(self::$_objects[$class][$id])) {
			return self::$_objects[$class][$id];
		}

		if (class_exists($class)) {
			$registry = new $class($id);
			return self::$_objects[$class][$id] = $registry;
		} else {
			trigger_error("class $class is not exists", E_USER_ERROR);
		}
	}

	static function getFullClassName($type) {
		if ($type === null) {
			$type = self::$_defaultType;
		} else {
			$type = strtolower($type);
		}

		$type = ucfirst($type);
		return 'Ebx_Registry_'.$type;
	}

}

interface Ebx_Storage {

	function read();

	function write($data = null);

	function clear();

	function isEmpty();

}

class Ebx_Http_RequestSimple {

	protected static $_globalArrays = array(
		'_GET','_POST','_COOKIE','_SESSION','_SERVER','_ENV'
	);

	protected $_query = array();

	protected function _get($array, $key = null, $type = null) {
		if (in_array($array, self::$_globalArrays)) {
			if ($key === null) {
				return $GLOBALS[$array];
			}
			if (isset($GLOBALS[$array][$key])) {
				if ($type !== null) {
					$value = $GLOBALS[$array][$key];
					settype($value, $type);
					return $value;
				}
				return $GLOBALS[$array][$key];
			}
		}
	}

	function getParam($key, $array, $default = null, $type = null) {
		$value = $this->_get($array, $key, $type);
		if ($value === null && $default !== null) {
			$value = $default;
		}
		return $value;
	}

	function get($key, $default = null, $type = null) {
		$value = $this->_get('_GET', $key, $type);
		if ($value === null && $default !== null) {
			$value = $default;
		}
		return $value;
	}

	function getPost($key = null, $default = null, $type = null) {
		if ($key === null) {
			return $this->_get('_POST');
		}
		$value = $this->_get('_POST', $key, $type);
		if ($value === null && $default !== null) {
			$value = $default;
		}
		return $value;
	}

	function getCookie($name, $default = null, $type = null) {
		$value = $this->_get('_COOKIE', $key, $type);
		if ($value === null && $default !== null) {
			$value = $default;
		}
		return $value;
	}

	function getServer($key) {
		return $this->_get('_SERVER', $key);
	}

	function getEnv($key) {
		return $this->_get('_ENV', $key);
	}

	function getQuery($intersect = null) {
		return $this->_get('_GET');
	}

	function isXmlHttpRequest() {
		return ($this->getHeader('X_REQUESTED_WITH') == 'XMLHttpRequest');
	}

	function isFlashRequest()
    {
        $header = strtolower($this->getHeader('USER_AGENT'));
        return (strstr($header, ' flash')) ? true : false;
    }

	function getHeader($header)
    {
        if (empty($header)) {
            trigger_error('Http header passed to '.__CLASS__.'::'.__METHOD__.' is empty');
        }

        $var = 'HTTP_' . strtoupper(str_replace('-', '_', $header));
		$var = $this->getServer($var);
        if (!empty($var)) {
            return $var;
        }

        if (function_exists('apache_request_headers')) {
            $headers = apache_request_headers();
            if (!empty($headers[$header])) {
                return $headers[$header];
            }
        }

        return false;
    }

}

class Ebx_Http_Request extends Ebx_Http_RequestSimple {

	private static $_instance = null;

	protected function __construct() { }

	static function getInstance() {
		if (self::$_instance === null) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}

}

class Ebx_Vars {

	const REGISTRY_ID = 'Ebx_Vars_Registry';

	private static $_instance = null;

	protected $_registry = null;

	protected function __construct() {
		$id = md5(self::REGISTRY_ID);
		$this->_registry = new Ebx_Registry_Array($id);
	}

	static function getInstance() {
		if (self::$_instance === null) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}

	static function get($key) {
		$instance = self::getInstance();
		return $instance->{$key};
	}

	static function set($key, $value) {
		$instance = self::getInstance();
		$instance->{$key} = $value;
	}

	static function has($key) {
		$instance = self::getInstance();
		return isset($instance->{$key});
	}

	static function clear($key) {
		$instance = self::getInstance();
		unset($instance->{$key});
	}

	function __set($key, $value) {
		$this->_registry->set($key, $value);
	}

	function __get($key) {
		return $this->_registry->get($key);
	}

	function __isset($key) {
		return $this->_registry->has($key);
	}

	function __unset($key) {
		$this->_registry->clear($key);
	}

}

interface Ebx_Helper_Interface {

	function direct($value, $options = null);

}

?>